﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using System.IO;

namespace OrderManagementSystem
{
    // 商品类
    [Serializable]
    public class Product
    {
        public string ProductId { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }

        public Product() { }

        public Product(string productId, string name, decimal price)
        {
            ProductId = productId;
            Name = name;
            Price = price;
        }

        public override string ToString()
        {
            return $"商品ID: {ProductId}, 名称: {Name}, 价格: {Price:C}";
        }

        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
                return false;

            Product other = (Product)obj;
            return ProductId == other.ProductId;
        }

        public override int GetHashCode()
        {
            return ProductId.GetHashCode();
        }
    }

    // 客户类
    [Serializable]
    public class Customer
    {
        public string CustomerId { get; set; }
        public string Name { get; set; }
        public string ContactInfo { get; set; }

        public Customer() { }

        public Customer(string customerId, string name, string contactInfo)
        {
            CustomerId = customerId;
            Name = name;
            ContactInfo = contactInfo;
        }

        public override string ToString()
        {
            return $"客户ID: {CustomerId}, 姓名: {Name}, 联系方式: {ContactInfo}";
        }

        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
                return false;

            Customer other = (Customer)obj;
            return CustomerId == other.CustomerId;
        }

        public override int GetHashCode()
        {
            return CustomerId.GetHashCode();
        }
    }

    // 订单明细类
    [Serializable]
    public class OrderDetail
    {
        public Product Product { get; set; }
        public int Quantity { get; set; }
        public decimal Amount => Product?.Price * Quantity ?? 0;

        public OrderDetail() { }

        public OrderDetail(Product product, int quantity)
        {
            Product = product;
            Quantity = quantity;
        }

        public override string ToString()
        {
            return $"{Product}, 数量: {Quantity}, 小计: {Amount:C}";
        }

        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
                return false;

            OrderDetail other = (OrderDetail)obj;
            return Product.Equals(other.Product);
        }

        public override int GetHashCode()
        {
            return Product?.GetHashCode() ?? 0;
        }
    }

    // 订单类
    [Serializable]
    public class Order : IComparable<Order>
    {
        public string OrderId { get; set; }
        public Customer Customer { get; set; }
        public List<OrderDetail> Details { get; set; }
        public DateTime OrderTime { get; set; }
        public decimal TotalAmount => Details?.Sum(d => d.Amount) ?? 0;

        public Order()
        {
            Details = new List<OrderDetail>();
            OrderTime = DateTime.Now;
        }

        public Order(string orderId, Customer customer) : this()
        {
            OrderId = orderId;
            Customer = customer;
        }

        public void AddDetail(OrderDetail detail)
        {
            if (Details.Contains(detail))
            {
                throw new ArgumentException("订单明细已存在");
            }
            Details.Add(detail);
        }

        public void RemoveDetail(Product product)
        {
            var detail = Details.FirstOrDefault(d => d.Product.Equals(product));
            if (detail == null)
            {
                throw new ArgumentException("订单中不存在该商品");
            }
            Details.Remove(detail);
        }

        public override string ToString()
        {
            string detailsStr = Details != null ? string.Join("\n  ", Details.Select(d => d.ToString())) : "无明细";
            return $"订单号: {OrderId}\n客户信息: {Customer}\n下单时间: {OrderTime}\n订单明细:\n  {detailsStr}\n总金额: {TotalAmount:C}";
        }

        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
                return false;

            Order other = (Order)obj;
            return OrderId == other.OrderId;
        }

        public override int GetHashCode()
        {
            return OrderId?.GetHashCode() ?? 0;
        }

        public int CompareTo(Order other)
        {
            if (other == null) return 1;
            return string.Compare(OrderId, other.OrderId, StringComparison.Ordinal);
        }
    }

    // 订单服务类
    public class OrderService
    {
        private List<Order> orders = new List<Order>();

        public void AddOrder(Order order)
        {
            if (order == null)
                throw new ArgumentNullException(nameof(order));

            if (orders.Any(o => o.OrderId == order.OrderId))
            {
                throw new ArgumentException($"订单 {order.OrderId} 已存在");
            }
            orders.Add(order);
        }

        public void RemoveOrder(string orderId)
        {
            var order = orders.FirstOrDefault(o => o.OrderId == orderId);
            if (order == null)
            {
                throw new ArgumentException($"订单 {orderId} 不存在，无法删除");
            }
            orders.Remove(order);
        }

        public void UpdateOrder(Order newOrder)
        {
            if (newOrder == null)
                throw new ArgumentNullException(nameof(newOrder));

            var index = orders.FindIndex(o => o.OrderId == newOrder.OrderId);
            if (index < 0)
            {
                throw new ArgumentException($"订单 {newOrder.OrderId} 不存在，无法修改");
            }
            orders[index] = newOrder;
        }

        public List<Order> GetAllOrders()
        {
            return orders.OrderBy(o => o.OrderId).ToList(); // 确保按订单号排序
        }

        public List<Order> QueryByOrderId(string orderId)
        {
            return orders.Where(o => o.OrderId.Contains(orderId))
                        .OrderBy(o => o.OrderId)
                        .ToList();
        }

        public List<Order> QueryByProductName(string productName)
        {
            return orders.Where(o => o.Details.Any(d =>
                           d.Product?.Name?.Contains(productName) ?? false))
                        .OrderBy(o => o.OrderId)
                        .ToList();
        }

        public List<Order> QueryByCustomer(string customerName)
        {
            return orders.Where(o => o.Customer?.Name?.Contains(customerName) ?? false)
                        .OrderBy(o => o.OrderId)
                        .ToList();
        }

        public List<Order> QueryByAmountRange(decimal min, decimal max)
        {
            return orders.Where(o => o.TotalAmount >= min && o.TotalAmount <= max)
                        .OrderBy(o => o.OrderId)
                        .ToList();
        }

        public void SortOrders(Comparison<Order> comparison = null)
        {
            orders.Sort(comparison ?? ((x, y) => x.CompareTo(y)));
        }

        public void Export(string filePath)
        {
            if (string.IsNullOrWhiteSpace(filePath))
                throw new ArgumentException("文件路径不能为空");

            try
            {
                var serializer = new XmlSerializer(typeof(List<Order>));
                using (var writer = new StreamWriter(filePath))
                {
                    serializer.Serialize(writer, orders);
                }
                Console.WriteLine($"成功导出 {orders.Count} 个订单到 {Path.GetFullPath(filePath)}");
            }
            catch (Exception ex)
            {
                throw new Exception($"导出失败: {ex.Message}", ex);
            }
        }

        public void Import(string filePath)
        {
            if (!File.Exists(filePath))
                throw new FileNotFoundException($"文件 {filePath} 不存在");

            List<Order> importedOrders;
            try
            {
                var serializer = new XmlSerializer(typeof(List<Order>));
                using (var reader = new StreamReader(filePath))
                {
                    importedOrders = (List<Order>)serializer.Deserialize(reader);
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"导入失败: {ex.Message}", ex);
            }

            if (importedOrders == null)
                throw new Exception("导入的文件不包含有效订单数据");

            var duplicateOrders = importedOrders
                .Where(io => orders.Any(o => o.OrderId == io.OrderId))
                .ToList();

            if (duplicateOrders.Any())
            {
                var duplicateOrderIds = string.Join(", ", duplicateOrders.Select(o => o.OrderId));
                throw new ArgumentException($"无法导入以下重复订单: {duplicateOrderIds}");
            }

            orders.AddRange(importedOrders);
            Console.WriteLine($"成功导入 {importedOrders.Count} 个订单");
        }
    }

    // 主程序
    class Program
    {
        static OrderService orderService = new OrderService();
        static List<Product> products = new List<Product>();
        static List<Customer> customers = new List<Customer>();

        static void Main(string[] args)
        {
            InitializeTestData();

            while (true)
            {
                try
                {
                    ShowMenu();
                    var input = Console.ReadLine();

                    if (!int.TryParse(input, out int choice))
                    {
                        Console.WriteLine("请输入有效数字！");
                        continue;
                    }

                    switch (choice)
                    {
                        case 1: AddOrder(); break;
                        case 2: RemoveOrder(); break;
                        case 3: UpdateOrder(); break;
                        case 4: QueryOrders(); break;
                        case 5: DisplayAllOrders(); break;
                        case 6: SortOrders(); break;
                        case 7: ExportToXml(); break;
                        case 8: ImportFromXml(); break;
                        case 0: return;
                        default: Console.WriteLine("无效选择！"); break;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"错误: {ex.Message}");
                }
            }
        }

        static void ShowMenu()
        {
            Console.WriteLine("\n=== 订单管理系统 ===");
            Console.WriteLine("1. 添加订单");
            Console.WriteLine("2. 删除订单");
            Console.WriteLine("3. 修改订单");
            Console.WriteLine("4. 查询订单");
            Console.WriteLine("5. 显示所有订单");
            Console.WriteLine("6. 排序订单");
            Console.WriteLine("7. 导出订单到XML");
            Console.WriteLine("8. 从XML导入订单");
            Console.WriteLine("0. 退出");
            Console.Write("请选择操作: ");
        }

        static void InitializeTestData()
        {
            // 初始化商品
            products.AddRange(new[]
            {
                new Product("P001", "笔记本电脑", 5999),
                new Product("P002", "智能手机", 3999),
                new Product("P003", "无线耳机", 299),
                new Product("P004", "游戏鼠标", 199)
            });

            // 初始化客户
            customers.AddRange(new[]
            {
                new Customer("C001", "张三", "13800138000"),
                new Customer("C002", "李四", "13900139000"),
                new Customer("C003", "王五", "13700137000")
            });

            // 添加测试订单，确保O001是第一个订单
            try
            {
                var order1 = new Order("O001", customers[0]);
                order1.AddDetail(new OrderDetail(products[0], 1));
                order1.AddDetail(new OrderDetail(products[3], 2));
                orderService.AddOrder(order1);

                var order2 = new Order("O002", customers[1]);
                order2.AddDetail(new OrderDetail(products[1], 1));
                order2.AddDetail(new OrderDetail(products[2], 3));
                orderService.AddOrder(order2);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"初始化测试数据时出错: {ex.Message}");
            }
        }

        static void AddOrder()
        {
            Console.Write("输入订单号: ");
            string orderId = Console.ReadLine();

            Console.WriteLine("选择客户:");
            for (int i = 0; i < customers.Count; i++)
            {
                Console.WriteLine($"{i + 1}. {customers[i]}");
            }
            Console.Write("请输入客户编号: ");
            int customerIndex = int.Parse(Console.ReadLine()) - 1;

            var order = new Order(orderId, customers[customerIndex]);

            while (true)
            {
                Console.WriteLine("\n选择商品 (0结束):");
                for (int i = 0; i < products.Count; i++)
                {
                    Console.WriteLine($"{i + 1}. {products[i]}");
                }
                Console.Write("请输入商品编号: ");
                int productIndex = int.Parse(Console.ReadLine()) - 1;

                if (productIndex == -1) break;

                Console.Write("输入购买数量: ");
                int quantity = int.Parse(Console.ReadLine());

                try
                {
                    order.AddDetail(new OrderDetail(products[productIndex], quantity));
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"添加商品失败: {ex.Message}");
                }
            }

            orderService.AddOrder(order);
            Console.WriteLine("订单添加成功！");
        }

        static void RemoveOrder()
        {
            Console.Write("输入要删除的订单号: ");
            string orderId = Console.ReadLine();

            orderService.RemoveOrder(orderId);
            Console.WriteLine("订单删除成功！");
        }

        static void UpdateOrder()
        {
            Console.Write("输入要修改的订单号: ");
            string orderId = Console.ReadLine();

            var existing = orderService.QueryByOrderId(orderId).FirstOrDefault();
            if (existing == null)
            {
                Console.WriteLine("订单不存在！");
                return;
            }

            Console.WriteLine("当前订单信息:");
            Console.WriteLine(existing);

            Console.Write("输入新订单号(留空保持不变): ");
            string newOrderId = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(newOrderId))
                newOrderId = orderId;

            Console.WriteLine("选择客户:");
            for (int i = 0; i < customers.Count; i++)
            {
                Console.WriteLine($"{i + 1}. {customers[i]}");
            }
            Console.Write("请输入客户编号: ");
            int customerIndex = int.Parse(Console.ReadLine()) - 1;

            var updatedOrder = new Order(newOrderId, customers[customerIndex]);

            Console.WriteLine("重新添加商品明细:");
            while (true)
            {
                Console.WriteLine("\n选择商品 (0结束):");
                for (int i = 0; i < products.Count; i++)
                {
                    Console.WriteLine($"{i + 1}. {products[i]}");
                }
                Console.Write("请输入商品编号: ");
                int productIndex = int.Parse(Console.ReadLine()) - 1;

                if (productIndex == -1) break;

                Console.Write("输入购买数量: ");
                int quantity = int.Parse(Console.ReadLine());

                try
                {
                    updatedOrder.AddDetail(new OrderDetail(products[productIndex], quantity));
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"添加商品失败: {ex.Message}");
                }
            }

            orderService.UpdateOrder(updatedOrder);
            Console.WriteLine("订单修改成功！");
        }

        static void QueryOrders()
        {
            Console.WriteLine("\n查询方式:");
            Console.WriteLine("1. 按订单号");
            Console.WriteLine("2. 按商品名称");
            Console.WriteLine("3. 按客户名称");
            Console.WriteLine("4. 按金额范围");
            Console.Write("请选择查询方式: ");

            int choice = int.Parse(Console.ReadLine());
            List<Order> results = null;

            switch (choice)
            {
                case 1:
                    Console.Write("输入订单号(可部分匹配): ");
                    results = orderService.QueryByOrderId(Console.ReadLine());
                    break;
                case 2:
                    Console.Write("输入商品名称(可部分匹配): ");
                    results = orderService.QueryByProductName(Console.ReadLine());
                    break;
                case 3:
                    Console.Write("输入客户名称(可部分匹配): ");
                    results = orderService.QueryByCustomer(Console.ReadLine());
                    break;
                case 4:
                    Console.Write("输入最小金额: ");
                    decimal min = decimal.Parse(Console.ReadLine());
                    Console.Write("输入最大金额: ");
                    results = orderService.QueryByAmountRange(min, decimal.Parse(Console.ReadLine()));
                    break;
                default:
                    Console.WriteLine("无效选择！");
                    return;
            }

            DisplayOrders(results);
        }

        static void DisplayAllOrders()
        {
            DisplayOrders(orderService.GetAllOrders());
        }

        static void DisplayOrders(List<Order> orders)
        {
            if (orders == null || orders.Count == 0)
            {
                Console.WriteLine("没有找到符合条件的订单");
                return;
            }

            Console.WriteLine($"\n找到 {orders.Count} 个订单:");
            foreach (var order in orders)
            {
                Console.WriteLine("-----------------------------");
                Console.WriteLine(order);
            }
            Console.WriteLine("-----------------------------");
        }

        static void SortOrders()
        {
            Console.WriteLine("\n排序方式:");
            Console.WriteLine("1. 按订单号");
            Console.WriteLine("2. 按总金额");
            Console.WriteLine("3. 按下单时间");
            Console.Write("请选择排序方式: ");

            int choice = int.Parse(Console.ReadLine());

            switch (choice)
            {
                case 1:
                    orderService.SortOrders();
                    Console.WriteLine("已按订单号排序");
                    break;
                case 2:
                    orderService.SortOrders((x, y) => x.TotalAmount.CompareTo(y.TotalAmount));
                    Console.WriteLine("已按总金额排序");
                    break;
                case 3:
                    orderService.SortOrders((x, y) => x.OrderTime.CompareTo(y.OrderTime));
                    Console.WriteLine("已按下单时间排序");
                    break;
                default:
                    Console.WriteLine("无效选择，使用默认排序");
                    orderService.SortOrders();
                    break;
            }

            DisplayAllOrders();
        }

        static void ExportToXml()
        {
            Console.Write("输入导出文件路径(如 orders.xml): ");
            string path = Console.ReadLine();

            try
            {
                orderService.Export(path);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"导出失败: {ex.Message}");
            }
        }

        static void ImportFromXml()
        {
            Console.Write("输入导入文件路径: ");
            string path = Console.ReadLine();

            try
            {
                orderService.Import(path);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"导入失败: {ex.Message}");
            }
        }
    }
}